/*
 * Copyright 2006 - 2007 The MITRE Corporation. All rights reserved.
 * Written by Ayal Spitz
 *
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 2.1
 * (the "License"); you may not use this file except in compliance
 * with the License and the following two conditions:
 * 
 * The US Government will not be charged any license fee and/or royalties 
 * related to this software.
 * 
 * Neither name of The MITRE Corporation; nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * You may obtain a copy of the License at
 *
 *     http://www.gnu.org/copyleft/lesser.txt
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */

package org.mitre.streamingRSS.xmpp;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.Form;
import org.jivesoftware.smackx.FormField;
import org.jivesoftware.smackx.muc.MultiUserChat;

/**
 * The Publisher class is designed to simplify the process of publishing in an
 * XMPP session. It is the base class of both spitz.ayal.irss.Publisher. This
 * class follows in the footsteps of Ruby on Rails and puts convention over 
 * configuration, ie there is an attempt to make smart defaults over long 
 * config files.
 * 
 * @author Ayal Spitz
 *
 */
public class Publisher extends Common{
// ### Class Fields ###########################################################
	protected Hashtable<String, MultiUserChat>		mucTable = null;
		
// ### Class Constructor ######################################################
	/**
	 * This constructor defaults to connecting to the localhost and using the
	 * default port (5222) for connecting to the XMPP server
	 */
	public Publisher(){ this("localhost"); }
	
	/**
	 * This constructor connects to the host passed in using the default port
	 * (5222) for connecting to the XMPP server
	 * 
	 * @param host					Either the host name or IP address of the 
	 * 								XMPP server. If "localhost" is passed in
	 * 								the constructor will attempt to turn
	 */
	public Publisher(String host){ this(host,5222); }

	/**
	 * This constructor connects to the host and port passed for the XMPP server
	 * 
	 * @param host					Either the host name or IP address of the 
	 * 								XMPP server. If "localhost" is passed in
	 * 								the constructor will attempt to turn
	 * @param port					The port to connect to the XMPP server
	 */
	public Publisher(String host,int port){
		super(host,port);
		mucTable = new Hashtable<String, MultiUserChat>();		
	}
	
// ### Class Methods ##########################################################
	/** 
	 * This method attempts to create a new multi-user chat room. This method
	 * gets the configuration form of the multi-user chat room and fills it in
	 * with defaults values other then the room owner, which is set to the
	 * users JID and sets the moderted room flag to true and sets the description.
	 * 
	 * @param mucName		The name of the chat room to be created
	 * @param desc			The description of the chat room to be created
	 * 
	 * @return				The chat room object
	 * 
	 * @throws XMPPException
	 */
	@SuppressWarnings({ "unused", "unchecked" })
	protected MultiUserChat createNewMUC(String mucName, String subject) throws XMPPException{
		MultiUserChat			muc = null;
		Form					form = null;
		Form					submitForm = null;
		FormField				field = null;
		List					owners = null;
		
		muc = createNewChatRoom(mucName);
		
		// Get the configuration form
		form = muc.getConfigurationForm();
		// Create a response form
		submitForm = form.createAnswerForm();
		
		// Fill the response form with the default values from the configuration form
		for (Iterator fields = form.getFields(); fields.hasNext();) {
			field = ((FormField)(fields.next()));
			if (!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable() != null) {
				// Sets the default value as the answer
				submitForm.setDefaultAnswer(field.getVariable());
				//System.out.println(field.getLabel() + " : " + field.getVariable());
			}
		}
				
		// Set the owner of the room
		owners = new ArrayList();
		owners.add(userJID);
		submitForm.setAnswer("muc#roomconfig_roomowners", owners);
		
		// Set the room to be moderated
		submitForm.setAnswer("muc#roomconfig_moderatedroom", true);
				
		// Send the completed form (with default values) to the server to configure the room
		muc.sendConfigurationForm(submitForm);

		mucTable.put(mucName, muc);
		
		// Set the subject of the chat room
		muc.changeSubject(subject);
		
		return muc;
	}

	protected MultiUserChat createNewMUC(String mucName) throws XMPPException{
		return createNewMUC(mucName, "");
	}
	
	/**
	 * This method fills out an answer on the form to be submited for chat room
	 * creation.
	 * 
	 * @param form		The form to be filled out
	 * @param key		The field to be filled out
	 * @param value		The value to be filled out
	 */
	@SuppressWarnings({ "unchecked", "unused" })
	private void setAnswer(Form form,String key,String value){
		List					list = null;
		
		list = new ArrayList();
		list.add(value);
		form.setAnswer(key, list);
	}
		
// === PublishIntf ============================================================
	public void publish(String mucName,String msg) throws XMPPException{
		MultiUserChat		muc = null;

		// Look up the feed to get a MUC object
		muc = mucTable.get(mucName);
		if (muc == null){
			muc = createNewMUC(mucName);
			mucTable.put(mucName, muc);
		}
		muc.sendMessage(msg);
	}
	
	public void publish(String mucName,List<String> msgs) throws XMPPException{
		MultiUserChat		muc = null;

		// Look up the feed to get a MUC object
		muc = mucTable.get(mucName);
		if (muc == null){
			muc = createNewMUC(mucName);
			mucTable.put(mucName, muc);
		}
		
		for(String msg:msgs){ muc.sendMessage(msg); }
	}

	public boolean topicExists(String mucName){ return mucTable.containsKey(mucName); }
	public void closeTopic(String mucName) throws XMPPException{
		MultiUserChat		muc = null;
		
		muc = mucTable.get(mucName);
		if (muc != null){ 
			muc.destroy("Room closed by owner.", "");
			mucTable.remove(mucName);
		}
	}
}